'use strict';

const yargs = require('yargs')

    , gulp = require('gulp')
    , onlyIf = require('gulp-if')
    , rename = require('gulp-rename')
    , sourcemaps = require('gulp-sourcemaps')
    , uglify = require('gulp-uglify')

    , del = require('del')
    , glob = require('glob')
    , path = require('path')

    , resolve = require('resolve')
    , browserify = require('browserify')
    , babelify = require('babelify')
    , source = require('vinyl-source-stream')
    , buffer = require('vinyl-buffer');

const DEBUG = !yargs.argv.production;

const SRC_HTML = './src/*.html'
    , SRC_JSX = './src/script/*.jsx';

const SRC_WATCH_JS = [
    './src/scripts/*.{js,jsx}'
    , './src/scripts/**/*.{js,jsx}'
];

const DIST = './dist';

process.chdir(__dirname);
let dependencies = () => {
    try {
        return Object.keys(
            require('./package.json').dependencies
        );
    }
    catch (e) {
        return [];
    }
}

let Bundler = (files) => {
    return browserify({
        transform: [
            babelify.configure({
                "presets": [ "react", "es2015" ]
            })
        ]
        , extensions: [ '.js', '.jsx' ]
        , entries: files || []

        , cache: {}
        , packageCache: {}
        , debug: DEBUG
    });
}

let bundleJs = (bundler, filename) => {
    return bundler
        .bundle()
        .pipe(source(filename))
        .pipe(buffer())
        .pipe(onlyIf(DEBUG
            , sourcemaps.init({ loadMaps: true })
        ))
        .pipe(rename({
            dirname: ''
            , extname: '.js'
        }))
        .pipe(onlyIf(DEBUG
            , sourcemaps.write('./')
        ))
        .pipe(onlyIf(!DEBUG
            , uglify()
        ))
        .pipe(gulp.dest(DIST + '/js'));
}

gulp.task('vendor-js', () => {
    let bundler = Bundler();
    dependencies().forEach((id) => {
        bundler.require(resolve.sync(id), { expose: id });
    });
    return bundleJs(bundler, 'vendor.js');
});

gulp.task('js', () => {
    glob.sync(SRC_JSX)
    .forEach((file) => {
        let bundler = Bundler(file);
        dependencies().forEach((lib) => {
            bundler.external(lib);
        });
        bundleJs(bundler, path.basename(file));
    });
});

gulp.task('html', () => {
    gulp.src(SRC_HTML)
        .pipe(gulp.dest(DIST))
});

gulp.task('build', [
    'vendor-js', 'js', 'html'
]);

gulp.task('clean', (cb) => {
    return del('./dist', { force: true })
        .then(() => cb);
});

gulp.task('watch:js', () => {
    return gulp.watch(SRC_WATCH_JS, [ 'js' ]);
});

gulp.task('watch:html', () => {
    return gulp.watch(SRC_HTML, [ 'html' ]);
});

gulp.task('watch', [
    'build', 'watch:js', 'watch:html'
]);